package whf.framework.util;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.beanutils.PropertyUtils;

import whf.framework.entity.AbstractEntity;
import whf.framework.entity.Entity;
import whf.framework.entity.PropertyTypeEnum;
import whf.framework.exception.DuplicateException;
import whf.framework.exception.PropertyException;
import whf.framework.ext.DictManagerImp;
import whf.framework.ext.entity.DictItem;
import whf.framework.i18n.ApplicationResource;
import whf.framework.meta.entity.IProperty;
import whf.framework.meta.entity.View;
import whf.framework.meta.entity.ViewProperty;
import whf.framework.meta.service.ViewServiceImp;

/**
 * @author wanghaifeng
 *
 */
@SuppressWarnings("unchecked")
public class BeanUtils {
	public final static  Object[] METHOD_EMPTY_PARAMS = new Object[]{};
	
	private BeanUtils() {
	}
	
	/**
	 * @modify wanghaifeng Aug 9, 2006 1:09:26 PM
	 * 为一对象中的一个属性设置值
	 * @param target
	 * @param propertyName
	 * @param value
	 * @throws PropertyException
	 */
	public static void setProperty(Object target, String propertyName, Object value) throws PropertyException{
		if(target == null || StringUtils.isEmpty(propertyName)) return;
		if(!hasProperty(target.getClass(), propertyName)) return;
		if(target instanceof Map) {
			((Map)target).put(propertyName, value);
			return;
		}
		try{
			PropertyDescriptor descriptor = getPropertyDescriptor(target.getClass(), propertyName);
			if(descriptor.getWriteMethod() != null) {
				PropertyUtils.setProperty(target, propertyName, value);
			} else {
				Method[] methods = target.getClass().getMethods();
				String mName = "set"+propertyName.substring(0,1).toUpperCase()+propertyName.substring(1);
				for(Method m:methods){
					if(mName.equals(m.getName())){
						m.invoke(target, new Object[]{value});
						return;
					}
				}
			}
		}catch(IllegalAccessException e){
			throw new PropertyException(e, target, propertyName);
		}catch(InvocationTargetException e){
			throw new PropertyException(e, target, propertyName);
		}catch(NoSuchMethodException e){
			throw new PropertyException(e, target, propertyName);
		}
	}
	
	/**
	 * 为一个对象赋一个简单对象的值
	 * @param target
	 * @param propertyType
	 * @param propertyName
	 * @param value
	 * @throws PropertyException 
	 */
	public static void setProperty(Object target,Class propertyType, String propertyName, String value) throws PropertyException{
		try{
			if(propertyType == int.class){
				setProperty(target, propertyName, new Integer(value ==null?0:Integer.parseInt(value)));
			} else if(propertyType == long.class){
				setProperty(target, propertyName, new Long(value == null?0:Long.parseLong(value)));
			} else if(propertyType == double.class){
				setProperty(target, propertyName, new Double(value == null?0:Double.parseDouble(value)));
			} else if(propertyType == float.class){
				setProperty(target, propertyName, new Float(value == null?0:Float.parseFloat(value)));
			} else if(propertyType == boolean.class){
				setProperty(target, propertyName, new Boolean(StringUtils.equalsIgnoreCase("true", value)));
			} else if(propertyType == java.util.Date.class){
				setProperty(target, propertyName, DateUtils.parseDate(value));
			} else if(propertyType == java.sql.Date.class){
				java.util.Date d = DateUtils.parseDate(value);
				if(d != null){
					setProperty(target, propertyName, new java.sql.Date(d.getTime()));
				} else {
					setProperty(target, propertyName, null);
				}
			}else{
				setProperty(target, propertyName, value);
			}
		}catch(Exception e){
			throw new PropertyException(e, target, propertyName);
		}
	}
	
	public static void copyProperty(Object target, String targetPropertyName, Object source, String sourcePropertyName) throws PropertyException{
		Object sourceValue = getProperty(source, sourcePropertyName);
		setProperty(target, targetPropertyName, sourceValue);
	}
	
	/**
	 * @modify wanghaifeng Aug 26, 2006 10:20:04 AM
	 * @param target
	 * @param source
	 * @throws PropertyException
	 */
	public static void copyProperties2(Object target, Object source) throws PropertyException{
		try{
			org.apache.commons.beanutils.BeanUtils.copyProperties(target, source);
		}catch(IllegalAccessException e){
			throw new PropertyException(e, target, "All Property");
		}catch(InvocationTargetException e){
			throw new PropertyException(e, target, "All Property");
		}
	}
	
	/**
	 * 将一个对象中的属性copy到另外一个对象的相同属性中,不计类型
	 * @modify wanghaifeng Sep 27, 2006 11:29:42 PM
	 * @param target
	 * @param source
	 * @throws PropertyException
	 */
	public static void copyProperties(Object target, Object source) {
		if(target == null || source == null) return;
		PropertyDescriptor[] sds = getPropertyDescriptors(source.getClass());
		for(PropertyDescriptor pd: sds){
			try{
				Object sourceValue = getProperty(source, pd.getName());
				if(hasProperty(target.getClass(), pd.getName())){
					setProperty(target,pd.getName(), sourceValue);
				}
			}catch(Exception e){
				continue;
			}
		}
	}
	
	/**
	 * 创建一个新对象，并把源对象中的属性值clone到目标对象中
	 * @modify wanghaifeng Nov 1, 2006 4:44:57 PM
	 * @param targetClass 目标类
	 * @param source 源对象
	 * @return clone后的对象
	 */
	public static Object cloneProperties(Class targetClass, Object source){
		try{
			Object target = targetClass.newInstance();
			copyProperties(target, source);
			return target;
		}catch(Exception e){
			return null;
		}
	}
	
	/**
	 * 将原对象中的对象属性复制到对应的目标对象中
	 * @modify wanghaifeng Jun 23, 2007 10:33:31 PM
	 * @param target
	 * @param source
	 * @param properties
	 */
	public static void cloneProperties(Object target, Object source, String[] properties){
		for(int i=0; properties != null && i < properties.length; i++){
			String property = properties[i];
			try{
				setProperty(target, property, getProperty(source, property));
			} catch(Exception e){
				System.out.println(e.getMessage());
				continue;
			}
		}
	}
	
	/**
	 * 复制对象，要求复制的对象必须有没有参数的构造函数或者带一个自己同类参数的构造函数；
	 * @modify wanghaifeng Aug 26, 2006 11:01:58 AM
	 * @param source 原对象
	 * @param properties 保留属性，类中如果存在这些属性则使用保留属性中的值替换，不予复制
	 * @param deepth 复制深度，针对于collection属性的情况
	 * @return 返回复制后的目标对象
	 */
	public static Object duplicate(Object source, Map<String, Object> properties, int deepth) throws DuplicateException{
		if(source == null) return null;
		Object target = null;
		Class targetClass = source.getClass();
		try{
			target = targetClass.newInstance(); //有空构造函数的情况
		}catch(Exception e){
			//
		}
		try{
			Constructor con = targetClass.getConstructor(new Class[]{targetClass}); //
			target = con.newInstance(new Object[]{source});
		}catch(Exception e){
			//
		}
		if(target == null) throw new DuplicateException(ApplicationResource.get("exception.duplicate.noavailable_constructors"));
		try{
			PropertyDescriptor[] descriptors = getPropertyDescriptors(targetClass);
			for(PropertyDescriptor desc: descriptors){
				String propertyName = desc.getName();
				Class propertyType = desc.getPropertyType();
				if(desc.getReadMethod() == null || desc.getWriteMethod() == null) continue;	//如果属性不同时具备读写属性
				if(properties != null && properties.containsKey(propertyName)){
					setProperty(target, propertyName, properties.get(propertyName));
					continue;
				}
				if(TypeUtils.isImplementsFrom(propertyType, Collection.class) && deepth > 0){					//对于集合属性复制其子元素
					Collection sourceCollections = (Collection)desc.getReadMethod().invoke(source, METHOD_EMPTY_PARAMS);
					Collection targetCollections = (Collection)desc.getReadMethod().invoke(target, METHOD_EMPTY_PARAMS);
					if(sourceCollections != null && targetCollections != null) {
						targetCollections.clear();
						for(Iterator it = sourceCollections.iterator(); it.hasNext(); ){
							Object o = it.next();
							if(o == null) continue;
							Object collectionPropertyValue = duplicate(o, properties, deepth -1 );
							if(collectionPropertyValue != null) {
								targetCollections.add(collectionPropertyValue);
							}
						}
					}
				} else {
					try{
						copyProperty(target, propertyName, source, propertyName);
					}catch(PropertyException e){
						continue;
					}
				}
			}
			return target;
		}catch(Exception e){
			throw new DuplicateException(e);
		}
	}

	/**
	 * @modify wanghaifeng Aug 26, 2006 10:19:57 AM
	 * @param obj 对象
	 * @param property 属性名称
	 * @return 属性值
	 * @throws PropertyException
	 */
	public static Object getProperty(Object obj, String property) throws PropertyException{
		if(obj == null || StringUtils.isEmpty(property)) return null;
		try{
			if(obj instanceof Map) {
				return ((Map)obj).get(property);
			} else {
				return PropertyUtils.getProperty(obj, property);
			}
		}catch(Exception e){
			throw new PropertyException(e, obj, property);
		}
	}
	
	/**
	 * 获取对象的字符串属性
	 * @param obj
	 * @param property
	 * @return
	 */
	public static String getStringProperty(Object obj, String property){
		if(StringUtils.isEmpty(property)) return null;
		try{
			if(property.indexOf(".") == -1)
				return org.apache.commons.beanutils.BeanUtils.getProperty(obj, property);
			else
				return org.apache.commons.beanutils.BeanUtils.getNestedProperty(obj, property);
		}catch(Exception e){
			return null;
		}
	}
	
	/**
	 * 获取属性的字符串表示
	 * 1.如果属性值是IBaseBO,那么只取名字
	 * 2.如果属性值是Collection,那么使用递归再显示
	 * 3.其它的显示toString
	 * @modify wanghaifeng Dec 20, 2006 9:27:38 AM
	 * @param obj
	 * @param property
	 * @param maxDeepth 最大深度,避免因只包含而出现的死循环
	 * @return
	 */
	public static String getSimpleProperty(Object obj, String property, int deepth, int maxDeepth){
		StringBuilder result = new StringBuilder();
		try{
			Object propertyValue = getProperty(obj, property);
			if(propertyValue != null){
				if(propertyValue instanceof Entity){
					result.append(((Entity)propertyValue).getName()).append(";");
				} else if(propertyValue instanceof Collection){
					Iterator it = ((Collection)propertyValue).iterator();
					while(it.hasNext() && deepth < maxDeepth){	//在这里设置,这样不因参数错误而导致的一次都不会执行
						result.append(getSimpleProperty(obj, property, deepth + 1, maxDeepth)).append(";");
					}
				} else if(propertyValue.getClass().isEnum()){
					String dictName = DictManagerImp.getDictManager().findDictItem(propertyValue.getClass().getName(), propertyValue.toString()).getName();
					result.append(dictName).append(";");
				} else {
					result.append(propertyValue.toString()).append(";");
				}
			}
		}catch(Exception e){
			//
		}
		String res = result.toString();
		if(res.endsWith(";")){
			res = res.substring(0, res.length() - 1);
		}
		return res;
	}
	
	/**
	 * 将元数据描述的属性翻译成字符串格式
	 * @modify wanghaifeng Dec 25, 2006 4:22:25 PM
	 * @param obj
	 * @param prop
	 * @return
	 */
	public static String translatePropertyToString(Object obj, IProperty prop) throws PropertyException{
		if(obj == null || prop == null) throw new IllegalArgumentException("Method BeanUtils.translatePropertyToString arguments error!");
		try{
			String result = null;
			Object propertyValue = getProperty(obj, prop.getName());
			if(propertyValue == null) return "";
			PropertyTypeEnum propertyType = getPropertyType(propertyValue, prop);
			if(propertyType == PropertyTypeEnum.COLLECTION){
				result = getObjectPropertyString((Collection)propertyValue, new String[]{"name"});
			} else if(propertyType == PropertyTypeEnum.ENTITY){
				result = ((Entity)propertyValue).getName();
			} else if(propertyType == PropertyTypeEnum.BOOLEAN){
				String b = propertyValue.toString();
				if(StringUtils.equalsIgnoreCase(b.trim(),"true")){
					result = ApplicationResource.get("boolean.true");
				} else {
					result = ApplicationResource.get("boolean.false");
				}
			} else if(propertyType == PropertyTypeEnum.DATETIME){
				String displayType = prop.getDisplayType();
				if(StringUtils.isEmpty(displayType)){
					result = DateUtils.formatDate((java.util.Date)propertyValue);
				} else {
					result = DateUtils.formatDate((java.util.Date)propertyValue, displayType);
				}
			} else if(propertyType == PropertyTypeEnum.DICT){
				DictItem dictItem = DictManagerImp.getDictManager().findDictItem(prop.getDictCategoryCode(), propertyValue.toString());
				result = dictItem == null? "": dictItem.getName();
			} else if(propertyType == PropertyTypeEnum.IMAGEFILE){
				String path = propertyValue == null?"":Base64.encode(propertyValue.toString());
				result = "/Download?path="+path;
			} else if(propertyType == PropertyTypeEnum.FILE){
				String path = propertyValue == null?"":Base64.encode(propertyValue.toString());
				result = "/Download?path="+path;
			} else {
				result = propertyValue == null? null: propertyValue.toString();
			}
			return result;
		}catch(Exception e){
			throw new PropertyException(e, obj, prop.getName());
		}
	}
	
	/**
	 * 根据值和属性对象判定属性类型
	 * @modify wanghaifeng Dec 25, 2006 4:30:20 PM
	 * @param propertyValue
	 * @param prop
	 * @return
	 */
	public static PropertyTypeEnum getPropertyType(Object propertyValue, IProperty prop){
		PropertyTypeEnum propertyType = PropertyTypeEnum.COMMON;
		if(prop == null){
			return propertyType;
		}
		String displayType = prop.getDisplayType();
		if(displayType == null) displayType = "";
		Class dataTypeClass = Utils.getClassByClassName(prop.getDataType());
		if(dataTypeClass != null ){
			if((propertyValue == null || propertyValue instanceof Entity || propertyValue instanceof Collection)  //只有确保propertyValue是IBaseBO才可以确定是业务对象类型 
					&& TypeUtils.isExtendsFrom(dataTypeClass, AbstractEntity.class)){
				propertyType = PropertyTypeEnum.ENTITY;
			}
		}
		if(propertyValue instanceof Collection && propertyType == PropertyTypeEnum.ENTITY){
			propertyType = PropertyTypeEnum.COLLECTION;
		}
		if(propertyType == PropertyTypeEnum.COMMON && !StringUtils.isEmpty(prop.getDictCategoryCode())){
			propertyType = PropertyTypeEnum.DICT;
		}
		if(propertyType != PropertyTypeEnum.ENTITY && propertyType != PropertyTypeEnum.DICT &&  propertyType != PropertyTypeEnum.COLLECTION){
			if(StringUtils.equalsIgnoreCase(prop.getDataType(), "boolean")){
				propertyType = PropertyTypeEnum.BOOLEAN;
			} else if(StringUtils.equalsIgnoreCase(prop.getDataType(), "double")){
				propertyType = PropertyTypeEnum.DOUBLE;
			} else if(StringUtils.equalsIgnoreCase(prop.getDataType(), "float")){
				propertyType = PropertyTypeEnum.FLOAT;
			} else if(StringUtils.equalsIgnoreCase(prop.getDataType(), "integer") || StringUtils.equalsIgnoreCase(prop.getDataType(), "int")){
				propertyType = PropertyTypeEnum.INTEGER;
			} else if(StringUtils.equalsIgnoreCase(prop.getDataType(), "long")){
				propertyType = PropertyTypeEnum.LONG;
			} else if(StringUtils.equalsIgnoreCase("String", prop.getDataType()) && (prop.isAllowMultiRows() || StringUtils.equalsIgnoreCase(prop.getDisplayType(), "TEXTAREA") )){
				propertyType = PropertyTypeEnum.TEXTAREA;
			} else if(StringUtils.equalsIgnoreCase(prop.getDataType(), "datetime") || 
					StringUtils.equalsIgnoreCase(prop.getDataType(), "date") || 
					StringUtils.equalsIgnoreCase(prop.getDataType(), "time")){
				propertyType = PropertyTypeEnum.DATETIME;
			} else if(StringUtils.startsWith(prop.getDataType(), "SYS_")){
				propertyType = PropertyTypeEnum.SYSTEM;
			} else if(displayType.toLowerCase().indexOf("file") >= 0 && 
					(StringUtils.equalsIgnoreCase(prop.getDataType(), "String") || StringUtils.equalsIgnoreCase(prop.getDataType(), String.class.getName()))){
				if(displayType == null? false: displayType.toLowerCase().indexOf("image") >= 0){
					propertyType = PropertyTypeEnum.IMAGEFILE;
				} else {
					propertyType = PropertyTypeEnum.FILE;
				}
			}
		}
		return propertyType;
	}
	
	/**
	 * 同上,缺省值为最大取三层
	 * @modify wanghaifeng Dec 20, 2006 9:41:39 AM
	 * @param obj
	 * @param property
	 * @return
	 */
	public static String getSimpleProperty(Object obj, String property){
		return getSimpleProperty(obj, property, 0, 3);
	}
	
	/**
	 * 获取一个集合中对象的属性列表的字符串表现
	 * @param coll 集合
	 * @param properties 需要输出的对象的属性
	 * @param objectSplitor 对象间的分隔符
	 * @param propertySplitor 对象中属性间的分隔符
	 * @return
	 */
	public static String getObjectPropertyString(Collection coll, String[] properties, String objectSplitor, String propertySplitor){
		if(coll == null || properties == null || properties.length == 0 ) return null;
		StringBuilder sb = new StringBuilder();
		for(Object o: coll){
			int pCount = 0;
			for(String prop : properties){
				try{
					sb.append(getProperty(o, prop));
					if(pCount < properties.length -1){
						sb.append(propertySplitor);
					}
				}catch(Exception e){
					//ignore
				}
				pCount ++;
			}
			sb.append(objectSplitor);
		}
		return sb.toString();
	}
	
	/**
	 * 同上，使用若干缺省值 
	 * @param coll
	 * @param properties
	 * @return
	 */
	public static String getObjectPropertyString(Collection coll, String[] properties){
		return getObjectPropertyString(coll, properties, ";",",");
	}
	
	/**
	 * 一个Class是否有某个属性
	 * @param cls
	 * @param propertyName
	 * @return
	 */
	public static boolean hasProperty(Class cls, String propertyName){
		PropertyDescriptor[] descriptors = getPropertyDescriptors(cls);
		for(int i=0; i< descriptors.length; i++){
			if(StringUtils.equalsIgnoreCase(descriptors[i].getName(), propertyName)){
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 获取Class的所有PropertyDesctiptor对象
	 * @param cls
	 * @return
	 */
	public static PropertyDescriptor[] getPropertyDescriptors(Class cls){
		return org.apache.commons.beanutils.PropertyUtils.getPropertyDescriptors(cls);
	}
	
	public static PropertyDescriptor getPropertyDescriptor(Class cls, String property){
		if(StringUtils.isEmpty(property)) return null;
		PropertyDescriptor[] descriptors = getPropertyDescriptors(cls);
		for(PropertyDescriptor descriptor: descriptors){
			if(StringUtils.equals(property, descriptor.getName())){
				return descriptor;
			}
		}
		return null;
	}
	
	/**
	 * 返回业务对象的类型是业务对象的属性描述
	 * @param modelClass
	 * @return 返回对象many-to-one属性的PropertyDescriptor
	 */
	public static final Map<String, PropertyDescriptor> getObjectPropertyDescriptors(Class modelClass){
		Map<String, PropertyDescriptor> map = Utils.newHashMap();
		PropertyDescriptor[] descriptors = getPropertyDescriptors(modelClass);
		for(int i=0;descriptors!=null && i<descriptors.length;i++){
			String propertyName = descriptors[i].getName();
			Class propertyType = descriptors[i].getPropertyType();
			if(TypeUtils.isExtendsFrom(propertyType, AbstractEntity.class)){
				map.put(propertyName, descriptors[i]);
			}
		}
		return map;
	}
	
	/**
	 * 返回一般属性的属性描述
	 * @param modelClass
	 * @return 返回对象一般属性的descriptors
	 */
	public static final Map<String, PropertyDescriptor> getReadablePropertyDescriptors(Class modelClass){
		Map<String, PropertyDescriptor> map = Utils.newHashMap();
		PropertyDescriptor[] descriptors = getPropertyDescriptors(modelClass);
		for(PropertyDescriptor descriptor: descriptors){
			if(TypeUtils.isPrimitiveType(descriptor.getPropertyType())){
				map.put(descriptor.getName(), descriptor);
			}
		}
		return map;
	}
	
	/**
	 * 把一个集合对象转换成业务对象集合的列表
	 * @modify wanghaifeng Oct 16, 2006 2:25:14 PM
	 * @param collection
	 * @return
	 */
	public static final List<Entity> convert2BoList(Collection collection){
		List<Entity> list = new ArrayList<Entity>();
		for(Iterator it = collection.iterator(); it.hasNext();){
			Object obj = it.next();
			if(obj != null && obj instanceof Entity){
				list.add((Entity)obj);
			}
		}
		return list;
	}
	
	/**
	 * 使用对象中的属性替换字符串中的指定值，字符串中的格式如下：$propertyName--对象中使用propertyName的属性替换
	 * $objectProperty.propertyName -- 使用对象中的对象属性的属性propertyName替换
	 * @param entity
	 * @param input
	 * @return
	 */
	public static String replaceByProperty(Object entity, String input){
		if(StringUtils.isEmpty(input) || entity == null || input.indexOf("$") < 0) return input;

		StringBuilder result = new StringBuilder();
		int startPoint = input.indexOf("${");
		int endPoint = input.indexOf("}", startPoint);
		while(startPoint >= 0 && endPoint > startPoint) {
			String str = input.substring(0, startPoint);
			if(!StringUtils.isEmpty(str)) {
				result.append(str);
			}
			String name = input.substring(startPoint + 2, endPoint);
			if(!StringUtils.isEmpty(name)) {
				String propValue = "";
				try{
					Object obj = getProperty(entity, name);
					if(obj != null){
						if(obj instanceof Entity){
							propValue = ((Entity)obj).getName();
						} else {
							propValue = obj.toString();
						}
					}
				} catch(Exception e){
				}
				result.append(propValue);
			}
			input = input.substring(endPoint + 1);
			startPoint = input.indexOf("${");
			endPoint = input.indexOf("}", startPoint);
		}
		if(!StringUtils.isEmpty(input)) {
			result.append(input);
		}
		return result.toString();
	}
	
	/**
	 * @modify wanghaifeng Aug 9, 2006 1:27:14 PM
	 * 从当前类或者上级类搜索对应的field
	 * @param cls
	 * @param field
	 * @return
	 */
	public static Field getField(Class cls, String field){
		try{
			return cls.getDeclaredField(field);
		} catch(NoSuchFieldException e){
			Class superClass = cls.getSuperclass();
			if(superClass != Object.class){
				return getField(superClass, field);
			}
		}
		return null;
	}
	
	public static Map<String, Method> getMethodsByParamTypes(Class modelClass, Class paramTypes[]) {
		if(modelClass == null || paramTypes == null) return null;
		Method[] methods = modelClass.getMethods();
		Map<String, Method> result = Utils.newHashMap();
		for(Method m:methods){
			Class[] methodParamTypes = m.getParameterTypes();
			if(methodParamTypes.length != paramTypes.length) continue;
			boolean found = true;
			for(int i =0; i< paramTypes.length; i++){
				if(paramTypes[i] != methodParamTypes[i]){
					found = false;
					break;
				}
			}
			if(found){
				result.put(m.getName(), m);
			}
		}
		return result;
	}
	
	/**
	 * 获取一个对象集合中的某一个属性的字符串列，属性值之间使用“；”分开
	 * @modify wanghaifeng Sep 5, 2006 9:47:21 PM
	 * @param source
	 * @param propertyName
	 * @return
	 */
	public static String getPropertyListString(Collection source, String propertyName){
		StringBuilder res = new StringBuilder();
		for(Iterator it = source.iterator(); it.hasNext(); ){
			String val = getStringProperty(it.next(), propertyName);
			if(val == null) continue;
			if(res.length() == 0){
				res.append(val);
			} else {
				res.append(";").append(val);
			}
		}
		return res.toString();
	}
	
	public static void main(String[] args) throws Exception{
		Map<String,Object> ps = Utils.newHashMap();
		ps.put("id", new Long(0));
		View view = (View)ViewServiceImp.getViewService().findByPrimaryKeyWithoutLazy(new Long(205));
		
		View newView = (View)duplicate(view, ps, 1);
		System.out.println(newView.getName());
		Set<ViewProperty> properties = newView.getProperties();
		for(IProperty prop: properties){
			if(prop == null) {
				System.out.println(prop);
				continue;
			}
			System.out.println(prop.getId()+":"+prop.getName()+":");
		}
		properties = view.getProperties();
		for(IProperty prop: properties){
			if(prop == null) {
				System.out.println(prop);
				continue;
			}
			System.out.println(((ViewProperty)prop).getView());
			System.out.println(prop.getId()+":"+prop.getName()+":");
		}
	}
}
